package com.zf.spring.microservice.zuul.common.filters.pre;

import java.io.IOException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.io.IOUtils;
import org.springframework.cloud.netflix.zuul.filters.Route;
import org.springframework.cloud.netflix.zuul.filters.RouteLocator;
import org.springframework.stereotype.Component;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.zf.spring.microservice.zuul.common.MergeRouteInfo;
import com.zf.spring.microservice.zuul.common.MergeStepInfo;

/**
 * 预处理服务聚合的请求
 * @author zhangfeng
 *
 */
@Component
public class PreMergeFilter extends ZuulFilter {
	private RouteLocator routeLocator;

	public PreMergeFilter(RouteLocator routeLocator) {
		this.routeLocator = routeLocator;
	}

	@Override
	public boolean shouldFilter() {
		RequestContext ctx = RequestContext.getCurrentContext();
		Object serviceId = ctx.get("serviceId");
		// merge开头的，即表示此请求是聚合服务
		return (ctx.getRouteHost() == null && serviceId != null && ctx
				.sendZuulResponse())
				&& serviceId.toString().startsWith("merge-");
	}

	@Override
	public Object run() {
		RequestContext ctx = RequestContext.getCurrentContext();
		Object serviceId = ctx.get("serviceId");
		// 此处移除serviceId，是为了让后续filter不再做处理。
		ctx.remove("serviceId");
		// 设置一个新属性
		ctx.set("mergeRouteId", serviceId.toString().replace("merge-", ""));
		HttpServletRequest request = ctx.getRequest();
		// 获取请求内容，此处为聚合信息
		String requestEntity = getRequestBody(request);
		JSONObject rules = JSONObject.parseObject(requestEntity);
		
		MergeRouteInfo mergeRouteInfo = new MergeRouteInfo();
		// start属性，表示此聚合服务从哪个步骤开始
		List<String> start = Arrays.asList(rules.getString("start").split(","));
		mergeRouteInfo.setStarts(start);
		Map<String, MergeStepInfo> steps = new HashMap<String, MergeStepInfo>();
		// 解析每个步骤的内容
		JSONArray stepsJson = rules.getJSONArray("steps");
		MergeStepInfo stepInfo = null;
		JSONObject stepJson = null;
		for (int i = 0; i < stepsJson.size(); i++) {
			stepInfo = new MergeStepInfo();
			stepJson = stepsJson.getJSONObject(i);
			// start属性中，配置的就是这个name
			stepInfo.setName(stepJson.getString("name"));
			// 服务的完整路径
			stepInfo.setFullPath(stepJson.getString("fullPath"));
			// http method
			stepInfo.setMethod(stepJson.getString("method"));
			// 下一步骤对应的name
			stepInfo.setThen(stepJson.getString("then"));
			// 服务请求参数
			// TODO 这里设想是可以取到上一步请求的响应结果作为参数，未实现
			stepInfo.setData(stepJson.getString("data"));
			// 根据fullpath匹配zuul中对应的location
			Route route = this.routeLocator.getMatchingRoute(stepInfo.getFullPath());
			stepInfo.setPath(route.getPath());
			stepInfo.setLocation(route.getLocation());
			steps.put(stepInfo.getName(), stepInfo);
		}
		mergeRouteInfo.setSteps(steps);
		// 将所有信息封装为一个对象，存在上下文中，预处理完毕
		ctx.set("mergeRouteInfo", mergeRouteInfo);
		return null;
	}

	private String getRequestBody(HttpServletRequest request) {
		String requestEntity = null;
		try {
			requestEntity = IOUtils.toString(request.getInputStream());
		} catch (IOException ex) {
			// no requestBody is ok.
		}
		return requestEntity;
	}

	@Override
	public String filterType() {
		return "pre";
	}

	@Override
	public int filterOrder() {
		return 6;
	}

}
